package com.olive.service.impl;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.olive.entity.Authority;
import com.olive.entity.User;
import com.olive.entity.UserAuthority;
import com.olive.mapper.AuthorityMapper;
import com.olive.mapper.UserAuthorityMapper;
import com.olive.mapper.UserMapper;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class MybatisUserDetailsService extends ServiceImpl<UserMapper, User> implements UserDetailsService {

    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private PasswordEncoder passwordEncoder;
    
    @Autowired
    private UserAuthorityMapper userAuthorityMapper;
    
    @Autowired
    private AuthorityMapper authorityMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        List<User> users = userMapper.queryUserByUsername(username);
        return users.stream()
        		.findFirst()
        		.orElseThrow(()->new UsernameNotFoundException("User Not Found"));
    }
    
    /**
     * 创建用户
     */
    @Override
    @Transactional
    public boolean save(User user) {
        try {
            String passwordNotEncode = user.getPassword();
            String passwordEncoded = passwordEncoder.encode(passwordNotEncode);
            user.setPassword(passwordEncoded);
            userMapper.insert(user);
            Set<Authority> authorities = user.getAuthorities();
            Set<Long> authorityIds = authorities.stream().map(Authority::getId).collect(Collectors.toSet());
            authorityIds.forEach(id -> {
                Authority authority = authorityMapper.selectById(id);
                if(authority != null){
                    Long userId = user.getId();
                    UserAuthority userAuthority = new UserAuthority();
                    userAuthority.setUserId(userId);
                    userAuthority.setAuthorityId(id);
                    userAuthorityMapper.insert(userAuthority);
                }
            });
            return true;
        } catch (Exception e) {
            log.error(e.getMessage(),e);
            return false;
        }
    }
    
}
